package com.amin.ms3d;

import com.math3d.Quaternion;
import com.system.FileUtils;
import com.system.GLApplication;
import com.system.GLLog;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class MS3DReader {
	/**
	 * 读取offset开始的4个字节构建为一个字节数组返回
	 * @param input
	 * @param offset
	 * @return
	 */
	public static byte[] get4ByteArray(byte[] input, int offset, int length){
		return new byte[]{input[offset], input[offset + 1], input[offset + 2], input[offset + 3]};
	}
	public static byte[] getByteArrayAtLength(byte[] input, int offset, int end){
		byte[] data = new byte[end - offset];
		for(int i = 0;i < data.length;i++){
			data[i] = input[offset + i];
		}
		return data;
	}
	public static char[] byteTochar(byte[] input){
		char result[] = new char[input.length];
		for(int i = 0;i < input.length;i++){
			result[i] = (char)input[i];
		}
		return result;
	}
	/**
	 * 将文件转成字节数组
	 * @param filePath
	 * @return
	 */
	public static byte[] toByteArray(String filePath){

		ByteArrayOutputStream bos=null;
		BufferedInputStream in = null;
		try {
			if(true){
				in = new BufferedInputStream(GLApplication.getContext().getResources().getAssets().open(filePath));
				bos = new ByteArrayOutputStream((int) in.available());

				int buf_size = 1024;
				byte[] buffer = new byte[buf_size];
				int len = 0;
				while (-1 != (len = in.read(buffer, 0, buf_size))) {
					bos.write(buffer, 0, len);
				}
				//return bos.toByteArray();
			}

		} catch (IOException e) {
		} finally {
			try {
				in.close();
				bos.close();
			} catch (IOException e) {
			}
		}
		return bos.toByteArray();
	}
	public static int bytes4ToInt(byte[] src) {
		int value;
		int offset = 0;
		value = (int) ((src[offset] & 0xFF)
				| ((src[offset+1] & 0xFF)<<8)
				| ((src[offset+2] & 0xFF)<<16)
				| ((src[offset+3] & 0xFF)<<24));
		return value;
	}
	public static int bytes2ToInt(byte[] src) {
		int value;
		int offset = 0;
		value = (int) ((src[offset] & 0xFF)
				| ((src[offset+1] & 0xFF)<<8)
				| ((0 & 0xFF)<<16)
				| ((0 & 0xFF)<<24));
		return value;
	}
	public static float bytesToFloat(byte[] b){
		//方法2 缓存输入，适用于SE/EE环境
		ByteBuffer buf = ByteBuffer.allocateDirect(4); //无额外内存的直接缓存
		buf=buf.order(ByteOrder.LITTLE_ENDIAN);//默认大端，小端用这行
		buf.put(b);
		buf.rewind();
		float f2=buf.getFloat();
		return f2;
	}
	public static int bytesToInt(byte[] b){
		//方法2 缓存输入，适用于SE/EE环境
		ByteBuffer buf = ByteBuffer.allocateDirect(4); //无额外内存的直接缓存
		buf=buf.order(ByteOrder.LITTLE_ENDIAN);//默认大端，小端用这行
		buf.put(b);
		buf.rewind();
		int i = buf.getInt();
		return i;
	}

	/**
	 * 加载MS3D
	 * @param filename
	 * @return
	 */
	public static final MS3DObj loadMS3D(String filename, MS3DObj mS3DObj){
		return parse(toByteArray(filename), mS3DObj);
	}

	/**
	 * 开始解析
	 * @param bytes
	 */
	private static final MS3DObj parse(byte[] bytes, MS3DObj ms3DObj){
		int offset = 0;
		//文件版本
		String versionID = String.valueOf(byteTochar(getByteArrayAtLength(bytes, offset, offset + 10))) + "" + String.valueOf(bytesToInt(getByteArrayAtLength(bytes, offset + 10, offset + 14)));
		offset += 14;
		//顶点数据
		int vertexCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
		offset += 2;
		List<MS3DObj.MS3DVertex> vertexs = new ArrayList<MS3DObj.MS3DVertex>();
		for(int i = 0;i < vertexCount;i++){
			MS3DObj.MS3DVertex vertex = new MS3DObj.MS3DVertex();
			vertex.mFlags = (int)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			vertex.mX = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			vertex.mY = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			vertex.mZ = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			vertex.mBoneID = (int)(getByteArrayAtLength(bytes, offset, offset + 1)[0]);
			offset += 1;
			vertex.mUnused = (int)(getByteArrayAtLength(bytes, offset, offset + 1)[0]);
			offset += 1;
			vertexs.add(vertex);
		}
		//图元数据
		List<MS3DObj.MS3DFace> faces = new ArrayList<MS3DObj.MS3DFace>();
		int faceCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
		offset += 2;
		for(int i = 0;i < faceCount;i++){
			MS3DObj.MS3DFace face = new MS3DObj.MS3DFace();
			face.mFlags = (short) bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			//3个顶点索引
			face.mVertexIndexs[0] = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			face.mVertexIndexs[1] = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			face.mVertexIndexs[2] = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			//3个法线
			MS3DObj.MS3DVecter n1 = new MS3DObj.MS3DVecter(bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4)), bytesToFloat(getByteArrayAtLength(bytes, offset + 4, offset + 8)), bytesToFloat(getByteArrayAtLength(bytes, offset + 8, offset + 12)));
			offset += 12;
			MS3DObj.MS3DVecter n2 = new MS3DObj.MS3DVecter(bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4)), bytesToFloat(getByteArrayAtLength(bytes, offset + 4, offset + 8)), bytesToFloat(getByteArrayAtLength(bytes, offset + 8, offset + 12)));
			offset += 12;
			MS3DObj.MS3DVecter n3 = new MS3DObj.MS3DVecter(bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4)), bytesToFloat(getByteArrayAtLength(bytes, offset + 4, offset + 8)), bytesToFloat(getByteArrayAtLength(bytes, offset + 8, offset + 12)));
			offset += 12;
			face.mNormals[0] = n1;
			face.mNormals[1] = n2;
			face.mNormals[2] = n3;
			//3组纹理坐标
			float u1 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			float u2 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			float u3 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			float v1 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			float v2 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			float v3 = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			face.mUvs[0][0] = u1;
			face.mUvs[0][1] = u2;
			face.mUvs[0][2] = u3;
			face.mUvs[1][0] = v1;
			face.mUvs[1][1] = v2;
			face.mUvs[1][2] = v3;
			face.mSmoothing = (int)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			face.mGroup = (int)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			faces.add(face);
		}
		//网格
		List<MS3DObj.MS3DMesh> meshs = new ArrayList<MS3DObj.MS3DMesh>();
		int meshCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
		offset += 2;
		for(int i = 0;i < meshCount;i++){
			MS3DObj.MS3DMesh mesh = new MS3DObj.MS3DMesh();
			mesh.mFlags = (int)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			mesh.mName = byteTochar(getByteArrayAtLength(bytes, offset, offset + 32));
			offset += 32;
			mesh.mNumTris = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			mesh.mFaceIndexs = new int[mesh.mNumTris];
			for(int f = 0;f < mesh.mNumTris;f++){
				mesh.mFaceIndexs[f] = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
				offset += 2;
			}
			mesh.mMaterial = getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			meshs.add(mesh);
		}
		//材质
		int materialCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
		offset += 2;
		List<MS3DObj.MS3DMaterial> materials = new ArrayList<MS3DObj.MS3DMaterial>();
		for(int i = 0;i < materialCount;i++){
			MS3DObj.MS3DMaterial material = new MS3DObj.MS3DMaterial();
			material.mName = byteTochar(getByteArrayAtLength(bytes, offset, offset + 32));
			offset += 32;
			//ambient
			material.mAmbient[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mAmbient[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mAmbient[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mAmbient[3] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//diffuse
			material.mDiffuse[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mDiffuse[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mDiffuse[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mDiffuse[3] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//specular
			material.mSpecular[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mSpecular[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mSpecular[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mSpecular[3] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//emissive
			material.mEmissive[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mEmissive[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mEmissive[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			material.mEmissive[3] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//shine
			material.mShine = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//transparency
			material.mTransparency = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//未使用
			material.mMode = (char)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			//纹理文件名
			material.mTexture = byteTochar(getByteArrayAtLength(bytes, offset, offset + 128));
			offset += 128;
			//透明纹理文件名
			material.mAlpha = byteTochar(getByteArrayAtLength(bytes, offset, offset + 128));
			offset += 128;
//			自身索引
//			material.mId = (char)getByteArrayAtLength(bytes, offset, offset + 1)[0];
//			offset += 1;
//			//备注
//			material.mComment = byteTochar(getByteArrayAtLength(bytes, offset, offset + 11));
//			offset += 11;
			materials.add(material);
		}
		//骨骼
//		offset += 12;		//这12个字节不知道是什么
		float animationFPS = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
		offset += 4;
		float currentTime = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
		offset += 4;
		int totalFrames = bytesToInt(getByteArrayAtLength(bytes, offset, offset + 4));
		offset += 4;
		float totalTime = totalFrames / animationFPS;
		int jointCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
		offset += 2;
		List<MS3DObj.MS3DJoint> joints = new ArrayList<MS3DObj.MS3DJoint>();
		for(int i = 0;i < jointCount;i++){
			MS3DObj.MS3DJoint joint = new MS3DObj.MS3DJoint();
			joint.mFlags = (int)getByteArrayAtLength(bytes, offset, offset + 1)[0];
			offset += 1;
			joint.mName = byteTochar(getByteArrayAtLength(bytes, offset, offset + 32));
			offset += 32;
			joint.mParent = byteTochar(getByteArrayAtLength(bytes, offset, offset + 32));
			offset += 32;
			joint.mRotation[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			joint.mRotation[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			joint.mRotation[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			joint.mPosition[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			joint.mPosition[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			joint.mPosition[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			//旋转帧数量
			int rotKeyFrameCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			joint.mNumRotFrames = rotKeyFrameCount;
			//平移帧数量
			int transKeyFrameCount = bytes2ToInt(getByteArrayAtLength(bytes, offset, offset + 2));
			offset += 2;
			joint.mNumTransFrames = transKeyFrameCount;
			if(rotKeyFrameCount > 0){
				joint.mRotKeyFrames = parseKeyFrame(bytes, offset, rotKeyFrameCount);
				offset += (4 * 4) * rotKeyFrameCount;
			}
			if(transKeyFrameCount > 0){
				joint.mTransKeyFrames = parseKeyFrame(bytes, offset, transKeyFrameCount);
				offset += (4 * 4) * transKeyFrameCount;
			}
			joints.add(joint);
		}
		if(ms3DObj == null){
			ms3DObj = new MS3DObj("null");
		}
		ms3DObj.mVertsionID = versionID;
		ms3DObj.mAnimationFPS = animationFPS;
		ms3DObj.mCurrentTime = currentTime;
		ms3DObj.mTotalFrames = totalFrames;
		ms3DObj.mTotalTime = totalTime;
		ms3DObj.mVertexs = vertexs;
		ms3DObj.mFaces = faces;
		ms3DObj.mMeshs = meshs;
		ms3DObj.mMaterials = materials;
		ms3DObj.mJoints = joints;
		return ms3DObj;
	}
	private static final MS3DObj.MS3DKeyFrame[] parseKeyFrame(byte[] bytes, int offset, int keyFrameCount){
		MS3DObj.MS3DKeyFrame keyFrames[] = new MS3DObj.MS3DKeyFrame[keyFrameCount];
		for(int i = 0;i < keyFrameCount;i++){
			MS3DObj.MS3DKeyFrame keyFrame = new MS3DObj.MS3DKeyFrame();
			keyFrame.mTime = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			keyFrame.mParams[0] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			keyFrame.mParams[1] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			keyFrame.mParams[2] = bytesToFloat(getByteArrayAtLength(bytes, offset, offset + 4));
			offset += 4;
			keyFrames[i] = keyFrame;
		}
		return keyFrames;
	}

}
